package com.spring.demo.core.job;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.JobDetailBean;

/**
 * 装配任务，创建任务的触发器、调度器
 * 
 * @author sean
 * 
 */
public class QuartzJobSchedulingListener implements
		ApplicationListener<ContextRefreshedEvent> {

	@Autowired
	private Scheduler scheduler;
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		logger.debug("QuartzJobSchedulingListener start!");

		ApplicationContext applicationContext = event.getApplicationContext();
		// 创建任务的trigger
		List<CronTriggerBean> triggerBeans = loadCronTriggerBeans(applicationContext);
		// 调度任务
		scheduleJobs(triggerBeans);

		logger.debug("QuartzJobSchedulingListener end!");
	}

	/**
	 * 调度任务
	 * 
	 * @param triggerBeans
	 */
	private void scheduleJobs(List<CronTriggerBean> triggerBeans) {

		for (CronTriggerBean cronTriggerBean : triggerBeans) {
			try {
				scheduler.scheduleJob(cronTriggerBean.getJobDetail(),
						cronTriggerBean);
			} catch (SchedulerException e) {
				throw new RuntimeException(e);
			}
		}
	}

	/**
	 * 创建任务的trigger
	 * 
	 * @param applicationContext
	 * @return
	 */
	private List<CronTriggerBean> loadCronTriggerBeans(
			ApplicationContext applicationContext) {
		Map<String, Object> jobBeans = applicationContext
				.getBeansWithAnnotation(QuartzJob.class);
		Set<String> beanNames = jobBeans.keySet();

		List<CronTriggerBean> cronTriggerBeans = new ArrayList<CronTriggerBean>();
		for (String beanName : beanNames) {
			CronTriggerBean triggerBean = null;
			Object job = jobBeans.get(beanName);
			try {
				triggerBean = buildCronTriggerBean(job);
			} catch (ParseException e) {
				throw new RuntimeException(e);
			}
			if (triggerBean != null) {
				cronTriggerBeans.add(triggerBean);
			}
		}

		return cronTriggerBeans;
	}

	/**
	 * 创建任务的trigger
	 * 
	 * @param job
	 * @return
	 * @throws ParseException
	 */
	private CronTriggerBean buildCronTriggerBean(Object job)
			throws ParseException {
		logger.debug("buildCronTriggerBean: " + job.getClass());

		CronTriggerBean cronTriggerBean = null;
		QuartzJob quartzJob = AnnotationUtils.findAnnotation(job.getClass(),
				QuartzJob.class);
		if (Job.class.isAssignableFrom(job.getClass())) {
			JobDetailBean jobDetailBean = new JobDetailBean();
			jobDetailBean.setJobClass(job.getClass());
			jobDetailBean.setName(quartzJob.name());

			cronTriggerBean = new CronTriggerBean();
			cronTriggerBean.setCronExpression(quartzJob.cronExp());
			cronTriggerBean.setName(quartzJob.name() + "_trigger");
			cronTriggerBean.setGroup(quartzJob.group());
			cronTriggerBean.setJobDetail(jobDetailBean);
		} else {
			throw new RuntimeException(job.getClass()
					+ " donesn't implemented " + Job.class);
		}

		return cronTriggerBean;
	}

}
